package com.zzj.ecology.system.service.impl.system;

import com.zzj.ecology.common.constant.GlobalConstant;
import com.zzj.ecology.common.constant.MenuConstant;
import com.zzj.ecology.common.utils.StringUtils;
import com.zzj.ecology.system.bean.system.SysMenu;
import com.zzj.ecology.system.bean.system.SysMenuExample;
import com.zzj.ecology.system.dto.HttpResult;
import com.zzj.ecology.system.domain.Page;
import com.zzj.ecology.system.bean.vo.dtree.DTree;
import com.zzj.ecology.system.bean.vo.dtree.DTreeResponse;
import com.zzj.ecology.system.mapper.system.SysMenuMapper;
import com.zzj.ecology.system.service.system.SysMenuService;
import com.zzj.ecology.system.utils.AppUtils;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;


/**
 * @ClassName SysMenuServiceImpl
 * @Description TODO
 * @Author zhijun zeng at 19:15 2020/4/1
 * @Version 1.0
 **/
@Transactional(rollbackFor = Exception.class)
@Service("sysMenuService")
@Slf4j
public class SysMenuServiceImpl implements SysMenuService {

    public static final Logger logger = LoggerFactory.getLogger(SysMenuServiceImpl.class);

    @Autowired
    private SysMenuMapper sysMenuMapper;

    /**
     * 用户登录后, 获取到用户相应的菜单 菜单delete_status='0'(菜单存在)
     * @param username
     * @return
     */
    public List<SysMenu> findOkTabMenuListByUsername(String username) {
        List<SysMenu> list = sysMenuMapper.findOkTabMenuListByUsername(username);

        List<SysMenu> collect = list.stream()
                .distinct()
                .filter(sysMenu -> sysMenu.getParentId() == 0
                        //&& !StringUtils.equals(MenuConstant.MenuType.BUTTON, sysMenu.getType())// 第一级的 parent_id = 0, 并且 类型是 C
                        && StringUtils.equals(sysMenu.getDeleteStatus(), GlobalConstant.DELETE_STATUS_NOT_DELETE))//过滤
                .map(sysMenu -> {
                    sysMenu.setChildren(getCurrentMenuChildren(sysMenu, list));
                    return sysMenu;
                })//给每一个对象映射
                .sorted(Comparator.comparingInt(SysMenu::getSortno))  //或者使用 .sorted((m1, m2) -> m1.getSortno()-m2.getSortno())
                .collect(Collectors.toList());

        return collect;
    }

    private List<SysMenu> getCurrentMenuChildren(SysMenu currentMenu, List<SysMenu> withinMenus) {
        List<SysMenu> children = withinMenus.stream()
                //.distinct()
                .filter(sysMenu -> sysMenu.getParentId() == currentMenu.getMenuId()
                        && !StringUtils.equals(MenuConstant.MenuType.BUTTON, sysMenu.getType())
                        && StringUtils.equals(sysMenu.getDeleteStatus(), GlobalConstant.DELETE_STATUS_NOT_DELETE))//过滤
                .map(sysMenu -> {
                    sysMenu.setChildren(getCurrentMenuChildren(sysMenu, withinMenus));
                    return sysMenu;
                })
                .sorted(Comparator.comparingInt(SysMenu::getSortno))//
                .collect(Collectors.toList());
        return children;
    }

    /**
     * 查询非按钮 下拉框 数据,用于列表中展示上级菜单下拉框
     * @return
     */
    public List<SysMenu> findNonButtonSelectBoxList() {
        List<SysMenu> list = sysMenuMapper.findNonButtonChildrensListByParentId(0);
        return list;
    }

    /**
     * laytable 分页查询数据
     * @param page
     * @return
     */
    public HttpResult findPageList(Page page) {
        int currentPage = page.getCurrentPage();
        Integer pageCounts = page.getPageCounts();
        int first = (currentPage - 1) * pageCounts;

        List<SysMenu> lists = sysMenuMapper.findWithoutChildrenPageList(first, pageCounts);
        page.getData().put(HttpResult.LIST_TAG, lists);// 当前页面数据

        SysMenuExample example = new SysMenuExample();
        SysMenuExample.Criteria criteria = example.createCriteria();
        criteria.andDeleteStatusEqualTo(GlobalConstant.DELETE_STATUS_NOT_DELETE);//delete_status='0' 的数据

        List<SysMenu> list1 = sysMenuMapper.selectByExample(example);//不分页总数据
        page.setTotalCounts(list1.size());

        return HttpResult.success().add(HttpResult.PAGE_TAG, page);
    }

    /**
     * 创建 一条 新的菜单记录, 如果有给定权限则建立菜单与权限的关联关系
     * @param menu
     * @return
     */
    public HttpResult createAndGrant(SysMenu menu) {
        int i = sysMenuMapper.insertSelective(menu);
        log.info("info - createAndGrant - {} - {}", this.getClass().getTypeName(),menu.toString());

        // 插入权限
        if (menu.getPermissionId() != null) {
            reGrantMenu(menu);
        }
        return HttpResult.success();
    }

    /**
     * 1) 修改 菜单 普通信息
     * 2) 修改 菜单 权限信息
     * @param menu
     * @return
     */
    public HttpResult updateAndGrant(SysMenu menu) {
        int i = sysMenuMapper.updateByPrimaryKeySelective(menu);
        log.info("info - updateAndGrant - {} - {}", this.getClass().getTypeName(),menu.toString());

        // 修改权限
        if (menu.getPermissionId() != null) {
            reGrantMenu(menu);
        }
        return i > 0 ? HttpResult.success() : HttpResult.error();
    }

    /**
     * 2) 修改 菜单 权限
     * @param menu
     * @return
     */
    public HttpResult rePerms(SysMenu menu) {
        int i = reGrantMenu(menu);
        return i > 0 ? HttpResult.success() : HttpResult.error();
    }

    /**
     * 查询当前登录用户的所有权限信息
     * @param username
     * @return
     */
    public List<String> findUserMenuPermsByUsername(String username) {
        List<SysMenu> list = sysMenuMapper.findUserMenuListByUsernameAndType(username, MenuConstant.MenuType.BUTTON);
        List<String> permsString = AppUtils.createPageButtonPermsList(list);
        return permsString;
    }

    /**
     * 批量删除菜单数据 ,标记删除,即修改 delete_status = '0' 状态位改成 '1', 记录修改人和修改时间.
     * @param menuids
     * @param username
     * @return
     */
    public HttpResult updateDeleteStatusByIds(List<Integer> menuids, String username) {
        // 修改 菜单 的 delete_status = 1
        int i = sysMenuMapper.updateDeleteStatusByIds(menuids, username, GlobalConstant.DELETE_STATUS_DELETE);
        return HttpResult.success();
    }

    /**
     * 查询所有未标识删除的 菜单树,delete_status = '0'的状态,基础数据 id, pid 数据
     * @return
     */
    public DTreeResponse dtree() {
        List<DTree> dTrees = sysMenuMapper.findDTreeList();
        DTreeResponse dTreeResponse = new DTreeResponse();
        dTreeResponse.setData(dTrees);
        return dTreeResponse;
    }

    /**
     * 菜单管理页面中,展示用页面.查询到的是delete_status='0'(未删)数据的基础数据
     * @return
     */
    public HttpResult treeTable() {
        List<SysMenu> menus = sysMenuMapper.treeTable();
        return HttpResult.success().add(HttpResult.DATA_TAG, menus);
    }


    /**
     * 根据 menuid 查询 Menu 与 Permission 的关联关系,存在关系则删除(包括 permission 的 delete_status 的状态为 delete 的情形)
     * @param menuId
     */
    private void findAndDeleteMenuPermissionRelation(Integer menuId) {
        List<SysMenu> list = findMenuPermissionRelationByMenuId(menuId);
        if (list.size() > 0) {
            deleteMenuPermissionRelationByMenuId(menuId);
        }
    }
    private List<SysMenu> findMenuPermissionRelationByMenuId(Integer menuId) {
        return sysMenuMapper.findMenuPermissionRelationByMenuId(menuId);
    }
    private void deleteMenuPermissionRelationByMenuId(Integer menuId) {
        sysMenuMapper.deleteMenuPermissionRelationByMenuId(menuId);
    }
    private int reGrantMenu(SysMenu menu) {
        if (menu.getMenuId() != null && menu.getPermissionId() != null) {
            findAndDeleteMenuPermissionRelation(menu.getMenuId());
            int i = sysMenuMapper.insertMenuPermissionRelation(menu.getMenuId(), menu.getPermissionId());
            return i;
        }
        return -1;
    }
}
